// src/composables/useImageAnnotator.ts

import { ref, onMounted, onUnmounted, watch, type Ref } from 'vue';

// --- 类型定义 ---
type Tool = 'pencil' | 'rectangle' | 'text';

interface Point {
  x: number;
  y: number;
}

interface Annotation {
  type: Tool;
  color: string;
  points: Point[];
  text?: string;
  lineWidth: number;
}

// Composable 函数
export function useImageAnnotator(
  canvasRef: Ref<HTMLCanvasElement | null>,
  emit: (event: 'export-base64', ...args: any[]) => void
) {
  // --- 核心状态 ---
  const ctx = ref<CanvasRenderingContext2D | null>(null);
  const annotations = ref<Annotation[]>([]);
  const loadedImage = ref<HTMLImageElement | null>(null);
  const imagePosition = ref<{ x: number; y: number; width: number; height: number } | null>(null);

  // --- 工具状态 ---
  const currentTool = ref<Tool>('pencil');
  const currentColor = ref<string>('#EF4444');
  const customColor = ref<string>('#000000');
  const presetColors = ['#EF4444', '#3B82F6', '#22C55E'];
  const currentLineWidth = ref<number>(3);
  const lineWidthOptions = [3, 6, 10, 16];

  // --- 交互状态 ---
  const isDrawing = ref(false);
  const currentDrawing = ref<Annotation | null>(null);

  // --- 新增: 缩放和平移状态 ---
  const scale = ref(1);
  const offset = ref({ x: 0, y: 0 });
  const isPanning = ref(false);
  const panStart = ref({ x: 0, y: 0 });

  // --- 新增: 历史记录 (撤销/重做) 状态 ---
  // 使用JSON字符串来存储状态快照，避免深拷贝的性能问题和引用陷阱
  const history = ref<string[]>([]);
  const historyIndex = ref(-1);
  const canUndo = ref(false);
  const canRedo = ref(false);


  // --- 核心绘图函数 ---
  const redrawCanvas = () => {
    if (!ctx.value || !canvasRef.value) return;
    const context = ctx.value;
    const canvas = canvasRef.value;

    context.save(); // 保存当前坐标系状态
    context.clearRect(0, 0, canvas.width, canvas.height); // 清空可视区域

    // 应用平移和缩放
    context.translate(offset.value.x, offset.value.y);
    context.scale(scale.value, scale.value);

    // 绘制网格 (现在也受变换影响)
    drawGrid();

    // 绘制图片
    if (loadedImage.value && imagePosition.value) {
      context.drawImage(
        loadedImage.value,
        imagePosition.value.x,
        imagePosition.value.y,
        imagePosition.value.width,
        imagePosition.value.height
      );
    }

    // 绘制所有标注
    annotations.value.forEach(annotation => drawAnnotation(context, annotation));

    // 绘制当前正在画的图形
    if (isDrawing.value && currentDrawing.value) {
      drawAnnotation(context, currentDrawing.value);
    }

    context.restore(); // 恢复坐标系，确保UI等不受影响
  };

  const drawGrid = () => {
    // 网格绘制逻辑可以根据需要进行优化，比如只绘制可视区域内的网格线
    // 这里为简化，保持原有逻辑，它会随画布缩放
    if (!ctx.value || !canvasRef.value) return;
    const context = ctx.value;
    const canvas = canvasRef.value;
    context.beginPath();
    context.strokeStyle = '#F1F1F1';
    context.lineWidth = 1 / scale.value; // 让网格线在缩放时保持纤细
    const gridSize = 20;

    // 考虑偏移和缩放来计算需要绘制的网格范围
    const startX = Math.floor(-offset.value.x / scale.value / gridSize) * gridSize;
    const endX = startX + canvas.width / scale.value + gridSize;
    const startY = Math.floor(-offset.value.y / scale.value / gridSize) * gridSize;
    const endY = startY + canvas.height / scale.value + gridSize;

    for (let x = startX; x <= endX; x += gridSize) {
      context.moveTo(x, startY);
      context.lineTo(x, endY);
    }
    for (let y = startY; y <= endY; y += gridSize) {
      context.moveTo(startX, y);
      context.lineTo(endX, y);
    }
    context.stroke();
  };

  const drawAnnotation = (context: CanvasRenderingContext2D, annotation: Annotation) => {
    context.strokeStyle = annotation.color;
    context.fillStyle = annotation.color;
    context.lineWidth = annotation.lineWidth; // 使用 annotation.lineWidth
    context.lineCap = 'round';
    context.lineJoin = 'round';

    switch (annotation.type) {
      case 'pencil':
        if (annotation.points.length < 2) return;
        context.beginPath();
        context.moveTo(annotation.points[0].x, annotation.points[0].y);
        for (let i = 1; i < annotation.points.length; i++) {
          context.lineTo(annotation.points[i].x, annotation.points[i].y);
        }
        context.stroke();
        break;
      case 'rectangle':
        if (annotation.points.length < 2) return;
        const start = annotation.points[0];
        const end = annotation.points[annotation.points.length - 1];
        const width = end.x - start.x;
        const height = end.y - start.y;

        // 保存当前 context 状态
        context.save();

        // 设置填充色的透明度 (例如 20%)
        // globalAlpha 会影响后续的所有绘制，所以需要 save 和 restore
        context.globalAlpha = 0.2;

        // 绘制填充矩形
        context.fillRect(start.x, start.y, width, height);

        // 恢复到 save 之前的状态（即 globalAlpha 恢复为 1）
        context.restore();

        // 绘制不透明的边框
        context.strokeRect(start.x, start.y, width, height);
      case 'text':
        if (!annotation.text || annotation.points.length === 0) return;
        const fontSize = 18 / scale.value; // 使字体大小在视觉上保持一致
        context.font = `${fontSize}px Arial`;
        context.fillText(annotation.text, annotation.points[0].x, annotation.points[0].y);
        break;
    }
  };

  // --- 事件坐标转换 ---
  const getTransformedMousePos = (event: MouseEvent | WheelEvent): Point => {
    const canvas = canvasRef.value;
    if (!canvas) return { x: 0, y: 0 };
    const rect = canvas.getBoundingClientRect();
    // 从屏幕坐标转换到画布的世界坐标
    const x = (event.clientX - rect.left - offset.value.x) / scale.value;
    const y = (event.clientY - rect.top - offset.value.y) / scale.value;
    return { x, y };
  };

  // --- 历史记录管理 ---
  const saveHistory = () => {
    // 移除当前索引之后的所有历史记录
    if (historyIndex.value < history.value.length - 1) {
      history.value.splice(historyIndex.value + 1);
    }
    // 添加新状态
    history.value.push(JSON.stringify(annotations.value));
    historyIndex.value++;
    updateUndoRedoState();
  };

  const updateUndoRedoState = () => {
    canUndo.value = historyIndex.value > 0;
    canRedo.value = historyIndex.value < history.value.length - 1;
  };

  const undo = () => {
    if (canUndo.value) {
      historyIndex.value--;
      annotations.value = JSON.parse(history.value[historyIndex.value]);
      updateUndoRedoState();
      redrawCanvas();
    }
  };

  const redo = () => {
    if (canRedo.value) {
      historyIndex.value++;
      annotations.value = JSON.parse(history.value[historyIndex.value]);
      updateUndoRedoState();
      redrawCanvas();
    }
  };


  // --- 事件处理器 ---
  const onMouseDown = (event: MouseEvent) => {
    if (event.button === 1 || event.altKey) { // 中键或按住Alt键平移
      isPanning.value = true;
      panStart.value = { x: event.clientX, y: event.clientY };
      return;
    }

    if (!loadedImage.value) return;
    const pos = getTransformedMousePos(event);
    isDrawing.value = true;

    if (currentTool.value === 'text') {
      const text = prompt('请输入文字内容:');
      if (text) {
        annotations.value.push({ type: 'text', color: currentColor.value, points: [pos], text, lineWidth: currentLineWidth.value });
        saveHistory(); // 保存历史
        redrawCanvas();
      }
      isDrawing.value = false;
      return;
    }

    currentDrawing.value = {
      type: currentTool.value,
      color: currentColor.value,
      points: [pos],
      lineWidth: currentLineWidth.value,
    };
  };

  const onMouseMove = (event: MouseEvent) => {
    if (isPanning.value) {
      const dx = event.clientX - panStart.value.x;
      const dy = event.clientY - panStart.value.y;
      offset.value.x += dx;
      offset.value.y += dy;
      panStart.value = { x: event.clientX, y: event.clientY };
      redrawCanvas();
      return;
    }

    if (!isDrawing.value || !currentDrawing.value) return;
    const pos = getTransformedMousePos(event);
    currentDrawing.value.points.push(pos);
    redrawCanvas(); // 实时预览
  };

  const onMouseUp = () => {
    if (isPanning.value) {
      isPanning.value = false;
      return;
    }
    if (!isDrawing.value || !currentDrawing.value) return;
    isDrawing.value = false;
    if (currentTool.value !== 'text') {
      annotations.value.push(currentDrawing.value);
      saveHistory(); // 绘制完成，保存历史
    }
    currentDrawing.value = null;
    redrawCanvas();
  };

  const onWheel = (event: WheelEvent) => {
    event.preventDefault();
    const pos = getTransformedMousePos(event);
    const scaleFactor = 1.1;
    let newScale;

    if (event.deltaY < 0) { // 放大
      newScale = scale.value * scaleFactor;
    } else { // 缩小
      newScale = scale.value / scaleFactor;
    }
    newScale = Math.max(0.1, Math.min(newScale, 10)); // 限制缩放范围

    // 计算新的偏移量，实现鼠标指向位置为中心的缩放
    offset.value.x = pos.x * (scale.value - newScale) + offset.value.x;
    offset.value.y = pos.y * (scale.value - newScale) + offset.value.y;

    scale.value = newScale;
    redrawCanvas();
  };


  // --- 工具栏功能 ---
  const setTool = (tool: Tool) => currentTool.value = tool;
  const setColor = (color: string) => currentColor.value = color;
  const setLineWidth = (width: number) => currentLineWidth.value = width;

  watch(customColor, (newColor) => currentColor.value = newColor);

  const getUsedColors = (): string[] => {
    // 使用 Set 数据结构来存储唯一的颜色值
    const colorSet = new Set<string>();

    // 遍历所有已完成的标注 (annotations.value 只包含当前有效的标注)
    annotations.value.forEach(annotation => {
      colorSet.add(annotation.color);
    });

    // 将 Set 转换成数组并返回
    return Array.from(colorSet);
  };

  const handleImageUpload = (event: Event) => {
    const target = event.target as HTMLInputElement;
    if (!target.files || !target.files[0] || !canvasRef.value) return;
    const file = target.files[0];
    const reader = new FileReader();
    reader.onload = (e) => {
      const img = new Image();
      img.onload = () => {
        loadedImage.value = img;
        annotations.value = [];

        // 重置变换和历史
        scale.value = 1;
        offset.value = { x: 0, y: 0 };
        history.value = [];
        historyIndex.value = -1;
        saveHistory(); // 保存初始空状态

        const canvas = canvasRef.value!;
        const canvasAspect = canvas.width / canvas.height;
        const imgAspect = img.width / img.height;
        let drawWidth, drawHeight, x, y;
        if (imgAspect > canvasAspect) {
          drawWidth = canvas.width * 0.9;
          drawHeight = drawWidth / imgAspect;
        } else {
          drawHeight = canvas.height * 0.9;
          drawWidth = drawHeight * imgAspect;
        }
        x = (canvas.width - drawWidth) / 2;
        y = (canvas.height - drawHeight) / 2;
        imagePosition.value = { x, y, width: drawWidth, height: drawHeight };
        redrawCanvas();
      };
      img.src = e.target?.result as string;
    };
    reader.readAsDataURL(file);
    target.value = '';
  };

  // --- 导出逻辑 ---
  const getCroppedCanvasAsBase64 = (format: 'image/png' | 'image/jpeg' = 'image/png'): string | null => {
    if (!loadedImage.value || !imagePosition.value) {
      alert('没有可导出的图片。'); return null;
    }
    const { x, y, width, height } = imagePosition.value;
    const exportCanvas = document.createElement('canvas');
    exportCanvas.width = width;
    exportCanvas.height = height;
    const exportCtx = exportCanvas.getContext('2d');
    if (!exportCtx) return null;

    // 关键: 创建一个临时的、未变换的画布来绘制最终结果
    const tempCanvas = document.createElement('canvas');
    tempCanvas.width = canvasRef.value!.width;
    tempCanvas.height = canvasRef.value!.height;
    const tempCtx = tempCanvas.getContext('2d');
    if (!tempCtx) return null;

    // 在临时画布上，应用变换并绘制所有内容
    tempCtx.translate(offset.value.x, offset.value.y);
    tempCtx.scale(scale.value, scale.value);
    if(loadedImage.value) tempCtx.drawImage(loadedImage.value, x, y, width, height);
    annotations.value.forEach(ann => drawAnnotation(tempCtx, ann));

    // 从临时画布上裁剪出所需区域
    exportCtx.drawImage(tempCanvas, x * scale.value + offset.value.x, y * scale.value + offset.value.y, width * scale.value, height * scale.value, 0, 0, width, height);

    return exportCanvas.toDataURL(format);
  };

  const exportImage = () => {
    const base64 = getCroppedCanvasAsBase64("image/png");
    if (!base64) return;
    const link = document.createElement('a');
    link.download = `annotated-${Date.now()}.png`;
    link.href = base64;
    document.body.appendChild(link);
    link.click();
    document.body.removeChild(link);
  };

  const generateAsBase64 = () => {
    const base64 = getCroppedCanvasAsBase64("image/png");
    if (!base64) return;
    return base64;
  }

  const exportAsBase64 = async () => {
    const base64 = getCroppedCanvasAsBase64();
    if (!base64) return;
    emit('export-base64', base64);
    try {
      await navigator.clipboard.writeText(base64);
      alert('Base64 已成功复制到剪贴板！');
    } catch (err) {
      console.error('无法复制到剪贴板: ', err);
      alert('复制到剪贴板失败。请在浏览器控制台查看Base64数据。');
      console.log('Base64 Data:', base64);
    }
  };

  // --- 初始化与清理 ---
  onMounted(() => {
    const canvas = canvasRef.value;
    if (!canvas) return;
    ctx.value = canvas.getContext('2d');

    // 动态调整canvas尺寸
    const wrapper = canvas.parentElement as HTMLElement;
    const resizeObserver = new ResizeObserver(() => {
      canvas.width = wrapper.clientWidth;
      canvas.height = wrapper.clientHeight;
      redrawCanvas();
    });
    resizeObserver.observe(wrapper);

    // 添加事件监听
    canvas.addEventListener('mousedown', onMouseDown);
    canvas.addEventListener('mousemove', onMouseMove);
    canvas.addEventListener('mouseup', onMouseUp);
    canvas.addEventListener('mouseleave', onMouseUp);
    canvas.addEventListener('wheel', onWheel, { passive: false });

    saveHistory(); // 保存初始的空状态

    onUnmounted(() => {
      resizeObserver.disconnect();
      canvas.removeEventListener('mousedown', onMouseDown);
      canvas.removeEventListener('mousemove', onMouseMove);
      canvas.removeEventListener('mouseup', onMouseUp);
      canvas.removeEventListener('mouseleave', onMouseUp);
      canvas.removeEventListener('wheel', onWheel);
    });
  });

  // --- 返回给组件使用的所有内容 ---
  return {
    // 状态
    currentTool,
    currentColor,
    customColor,
    presetColors,
    currentLineWidth,
    lineWidthOptions,
    canUndo,
    canRedo,
    // 方法
    setTool,
    setColor,
    setLineWidth,
    handleImageUpload,
    exportImage,
    exportAsBase64,
    generateAsBase64,
    undo,
    redo,
    getUsedColors
  };
}
